Rustの真の習得は、 DRY(繰り返しを避ける) 原則から始まります。汎用構文に手を伸ばす前に、 具体的な抽象化という道を歩まなければなりません。小売アプリが価格(i32)とセンサー温度(f32)を比較する場面を想像してください。比較ロジックをコピペすると、 技術的負債 重複の影の中でバグが繁栄する状況を作り出します。
1. リファクタリングのワークフロー
重複から洗練されたコードへ移行するためには、以下の3段階の抽出プロセスに従ってください: 識別する 繰り返されるロジックを、 抽出する 明確な入出力を持つ関数本体に、そのロジックを、そして 更新する 元の呼び出し箇所を新しい関数を使用するように更新します。
2. 具体的ロジックの限界
一方で、 リスト10-3 ロジックを成功裏に抽象化していますが、依然として 具体的なデータ型に縛られています。ロジックの重複は解消されますが、 型の重複にさらされるリスクが残ります。この壁が、 抽象型 ($
main.py
TERMINALbash — 80x24
> Ready. Click "Run" to execute.
>
QUESTION 1
According to the 'Path to Robust Abstraction', what is the first step in the refactoring workflow?
Defining a generic type parameter <T>.
Identifying repeated logic in the codebase.
Compiling the code to check for borrow errors.
Implementing the PartialOrd trait.
✅ Correct!
Correct! You must first recognize duplication before you can abstract it.❌ Incorrect
Generic parameters come later. The first step is identification of duplicate concrete logic.QUESTION 2
What does Listing 10-4 represent in this lesson context?
A fully generic implementation of a search algorithm.
Two functions that differ only in names and signatures (Technical Debt).
A specialized trait for temperature sensors.
The final state of robust abstraction.
✅ Correct!
Yes. Listing 10-4 shows the duplication (i32 vs char) that we want to eliminate.❌ Incorrect
Listing 10-4 is the 'before' state, showing the cost of duplication across types.QUESTION 3
Why is Listing 10-3 considered a 'partial' success in abstraction?
It fails to find the largest number correctly.
It requires the heap for all calculations.
It abstracts the logic but remains bound to a Concrete Data Type (i32).
It uses too many lifetime annotations.
✅ Correct!
Exactly. It handles logic duplication but not type duplication.❌ Incorrect
The logic is correct, but it is restricted to i32, meaning it isn't truly generic yet.QUESTION 4
What is the specific 'debt' created by having two functions with identical logic for different types?
Increased binary size due to monomorphization.
Logic updates must be applied manually in multiple places.
Compile times are significantly reduced.
It bypasses the borrow checker.
✅ Correct!
This is the core of maintenance debt—updating the 'comparison' logic in one place won't fix it in the other.❌ Incorrect
Manual updates in multiple places increase the surface area for bugs and logic drift.QUESTION 5
What serves as the 'catalyst' for moving toward Abstract Types like Generics?
The desire for slower runtime performance.
Running out of stack memory.
The realization that concrete abstraction doesn't solve type duplication.
The need for global variables.
✅ Correct!
Generics are the solution to the limitations of concrete functions like the one in Listing 10-3.❌ Incorrect
Generics solve the problem of repeating logic across different types.Case Study: Scaling the Retail App
Applying Concrete Abstraction to Price and Inventory Data
You have a retail application that currently uses two loops: one to find the most expensive 'Item' (Price: i32) and one to find the highest 'Quantity' (Stock: i32) in a warehouse list. You want to apply the 'Path to Robust Abstraction'.
Q
1. How would you apply the first two steps of the refactoring workflow to these two loops?
Solution:
First, identify that both loops use identical comparison logic (if item > current_max). Second, extract this into a single function `fn largest(list: &[i32]) -> &i32` that takes a slice of integers and returns a reference to the max.
First, identify that both loops use identical comparison logic (if item > current_max). Second, extract this into a single function `fn largest(list: &[i32]) -> &i32` that takes a slice of integers and returns a reference to the max.
Q
2. If your app later adds 'Temperature' as an f32, why does the abstraction in Listing 10-3 fail to help?
Solution:
Listing 10-3 is tied to a Concrete Data Type (i32). While the logic is the same, the function signature `&[i32]` will reject a slice of `f32`, forcing you back into type duplication until Generics are introduced.
Listing 10-3 is tied to a Concrete Data Type (i32). While the logic is the same, the function signature `&[i32]` will reject a slice of `f32`, forcing you back into type duplication until Generics are introduced.